home *** CD-ROM | disk | FTP | other *** search
/ Nejlepší hry / Nejlepsi hry.iso / hry / plane arcade / planearcade.exe / tank3.bmp / stencil.cpp < prev    next >
C/C++ Source or Header  |  2004-09-18  |  10KB  |  368 lines

  1.  
  2. #include "main.h"
  3.  
  4. STENCIL StencilShadow;
  5.  
  6. //------------------------------------------------------------------
  7. // Name: STENCIL()
  8. // Desc: konstruktor
  9. //------------------------------------------------------------------
  10. STENCIL::STENCIL()
  11. {
  12.     SquareVB = NULL;
  13.  
  14.     NumVertices = 0;
  15.  
  16.     LightPosition = Get3D( 100.0f,100.0f,100.0f);
  17.  
  18. }
  19.  
  20. //------------------------------------------------------------------
  21. // Name: ~STENCIL()
  22. // Desc: destruktor
  23. //------------------------------------------------------------------
  24. STENCIL::~STENCIL()
  25. {
  26.  
  27.     if (SquareVB != NULL)
  28.         SquareVB->Release();
  29.  
  30. }
  31.  
  32.  
  33. //------------------------------------------------------------------
  34. // Name: Initialize()
  35. // Desc: inicializacia 
  36. //------------------------------------------------------------------
  37. void STENCIL::Initialize()
  38. {
  39.     //ak nieje zapnuty stencil prec
  40.     if (Engine.StencilShadows == false)
  41.         return;
  42.     
  43.     LogPrint("Inicializuje Stencil");
  44.  
  45.     //////////////
  46.     //Big Square//
  47.     //////////////
  48.     if (FAILED(g_pd3dDevice->CreateVertexBuffer( 4*sizeof(CUSTOMVERTEXSTENCILSQUARE ),
  49.                                       D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEXSTENCILSQUARE ,
  50.                                       D3DPOOL_DEFAULT, &SquareVB, NULL )))
  51.     {
  52.         LogPrint(" Chyba pri vytvarani VB");
  53.     }
  54.     else
  55.     {
  56.         LogPrint(" Vertex Buffer vytvoreny");
  57.     }
  58.  
  59.  
  60.     CUSTOMVERTEXSTENCILSQUARE *v;
  61.  
  62.     SquareVB->Lock( 0, 0, (void**)&v, 0 );
  63.     {
  64.         v[0].p = D3DXVECTOR4(  0, (float)Engine.Height, 0.0f, 1.0f );
  65.         v[1].p = D3DXVECTOR4(  0, 0, 0.0f, 1.0f );
  66.         v[2].p = D3DXVECTOR4( (float)Engine.Width, (float)Engine.Height, 0.0f, 1.0f );
  67.         v[3].p = D3DXVECTOR4( (float)Engine.Width, 0.0f, 0.0f, 1.0f );
  68.         v[0].color = 0x60000000;
  69.         v[1].color = 0x60000000;
  70.         v[2].color = 0x60000000;
  71.         v[3].color = 0x60000000;
  72.     }
  73.     SquareVB->Unlock();
  74.  
  75.  
  76. }
  77.  
  78.  
  79. //------------------------------------------------------------------
  80. // Name: AddEdge()
  81. // Desc: prida quad od hrany
  82. //------------------------------------------------------------------
  83. void STENCIL::AddEdge(VECTOR3D V1,VECTOR3D V2)
  84. {
  85.     //ak nieje zapnuty stencil prec
  86.     if (Engine.StencilShadows == false)
  87.         return;
  88.  
  89.  
  90.     Edge[NumEdges].V1 = V1;
  91.     Edge[NumEdges].V2 = V2;
  92.     NumEdges++;
  93.  
  94. }
  95.  
  96. //------------------------------------------------------------------
  97. // Name: ProcessEdge()
  98. // Desc: z hrany urobi quad
  99. //------------------------------------------------------------------
  100. void STENCIL::AddQuad(VECTOR3D V1,VECTOR3D V2,VECTOR3D LightPos)
  101. {
  102.  
  103.     //ak nieje zapnuty stencil prec
  104.     if (Engine.StencilShadows == false)
  105.         return;
  106.  
  107.  
  108.     VECTOR3D Sme1,Sme2;
  109.     Sub(&Sme1,V1,LightPos);
  110.     Sub(&Sme2,V2,LightPos);
  111.  
  112.     VECTOR3D E0 ;
  113.     VECTOR3D E1 ;
  114.     VECTOR3D E2 ;
  115.     VECTOR3D E3 ;
  116.  
  117.     E0.X = V1.X ;
  118.     E0.Y = V1.Y ;
  119.     E0.Z = V1.Z ;
  120.  
  121.     E1.X = V2.X ;
  122.     E1.Y = V2.Y ;
  123.     E1.Z = V2.Z ;
  124.  
  125.     E2.X = V1.X + Sme1.X*100.0f;
  126.     E2.Y = V1.Y + Sme1.Y*100.0f;
  127.     E2.Z = V1.Z + Sme1.Z*100.0f;
  128.  
  129.     E3.X = V2.X + Sme2.X*100.0f;
  130.     E3.Y = V2.Y + Sme2.Y*100.0f;
  131.     E3.Z = V2.Z + Sme2.Z*100.0f;
  132.  
  133.     /////
  134.     //1//
  135.     /////
  136.     Vertices[NumVertices].x = E0.X;
  137.     Vertices[NumVertices].y = E0.Y;
  138.     Vertices[NumVertices].z = E0.Z;
  139.     NumVertices++;
  140.  
  141.     Vertices[NumVertices].x = E1.X;
  142.     Vertices[NumVertices].y = E1.Y;
  143.     Vertices[NumVertices].z = E1.Z;
  144.     NumVertices++;
  145.  
  146.     Vertices[NumVertices].x = E2.X;
  147.     Vertices[NumVertices].y = E2.Y;
  148.     Vertices[NumVertices].z = E2.Z;
  149.     NumVertices++;
  150.  
  151.     /////
  152.     //2//
  153.     /////
  154.     Vertices[NumVertices].x = E2.X;
  155.     Vertices[NumVertices].y = E2.Y;
  156.     Vertices[NumVertices].z = E2.Z;
  157.     NumVertices++;
  158.  
  159.     Vertices[NumVertices].x = E1.X;
  160.     Vertices[NumVertices].y = E1.Y;
  161.     Vertices[NumVertices].z = E1.Z;
  162.     NumVertices++;
  163.  
  164.     Vertices[NumVertices].x = E3.X;
  165.     Vertices[NumVertices].y = E3.Y;
  166.     Vertices[NumVertices].z = E3.Z;
  167.     NumVertices++;
  168.  
  169. }
  170.  
  171. //------------------------------------------------------------------
  172. // Name: ProcessEdge()
  173. // Desc: Vyberie iba hrany ktore s nikim nesusedia
  174. //------------------------------------------------------------------
  175. void STENCIL::ProcessEdge(VECTOR3D LightPos)
  176. {
  177.  
  178.     //ak nieje zapnuty stencil prec
  179.     if (Engine.StencilShadows == false)
  180.         return;
  181.  
  182.  
  183.     int NumIdent = 0,i,u;
  184.  
  185.     for    (i=0;i<NumEdges;i++)
  186.     {
  187.         NumIdent = 0;
  188.  
  189.         for (u=0;u<NumEdges;u++)
  190.         {
  191.              if(( (Edge[u].V1.X == Edge[i].V1.X && Edge[u].V1.Y == Edge[i].V1.Y && Edge[u].V1.Z == Edge[i].V1.Z)  &&
  192.                  (Edge[u].V2.X == Edge[i].V2.X && Edge[u].V2.Y == Edge[i].V2.Y && Edge[u].V2.Z == Edge[i].V2.Z) )||
  193.                ( (Edge[u].V1.X == Edge[i].V2.X && Edge[u].V1.Y == Edge[i].V2.Y && Edge[u].V1.Z == Edge[i].V2.Z)  &&
  194.                  (Edge[u].V2.X == Edge[i].V1.X && Edge[u].V2.Y == Edge[i].V1.Y && Edge[u].V2.Z == Edge[i].V1.Z) ))
  195.             {
  196.                 NumIdent++;
  197.             }
  198.         }
  199.  
  200.         if (NumIdent == 1)
  201.         {
  202.             AddQuad(Edge[i].V1,Edge[i].V2,LightPos);
  203.         }
  204.  
  205.  
  206.     }
  207.  
  208. }
  209.  
  210. //------------------------------------------------------------------
  211. // Name: RenderShadowQuads()
  212. // Desc: vyrenderuje quady
  213. //------------------------------------------------------------------
  214. void STENCIL::RenderShadowQuads()
  215. {
  216.  
  217.     //ak nieje zapnuty stencil prec
  218.     if (Engine.StencilShadows == false)
  219.         return;
  220.  
  221.     g_pd3dDevice->SetFVF( D3DFVF_XYZ );
  222.     g_pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLELIST, NumVertices/3,
  223.                                  Vertices, sizeof(D3DXVECTOR3) );
  224.  
  225.  
  226. }
  227.  
  228. //------------------------------------------------------------------
  229. // Name: RenderShadow()
  230. // Desc: vyrenderuje hotovy tien
  231. //------------------------------------------------------------------
  232. void STENCIL::RenderShadow()
  233. {
  234.  
  235.     //ak nieje zapnuty stencil prec
  236.     if (Engine.StencilShadows == false)
  237.         return;
  238.  
  239.     RenderShadowBuffer();
  240.     RenderShadowScreen();
  241.  
  242.     //reset
  243.     NumVertices = 0;
  244.     NumEdges = 0;
  245.  
  246. }
  247.  
  248. //------------------------------------------------------------------
  249. // Name: RenderShadowBuffer()
  250. // Desc: vyrenderuje tien do stencil bufferu
  251. //------------------------------------------------------------------
  252. void STENCIL::RenderShadowBuffer()
  253. {
  254.  
  255.     //ak nieje zapnuty stencil prec
  256.     if (Engine.StencilShadows == false)
  257.         return;
  258.  
  259.     // Disable z-buffer writes (note: z-testing still occurs), and enable the
  260.     // stencil-buffer
  261.     g_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE,  FALSE );
  262.     g_pd3dDevice->SetRenderState( D3DRS_STENCILENABLE, TRUE );
  263.  
  264.     // Dont bother with interpolating color
  265.     g_pd3dDevice->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_FLAT );
  266.  
  267.     // Set up stencil compare fuction, reference value, and masks.
  268.     // Stencil test passes if ((ref & mask) cmpfn (stencil & mask)) is true.
  269.     // Note: since we set up the stencil-test to always pass, the STENCILFAIL
  270.     // renderstate is really not needed.
  271.  
  272.     g_pd3dDevice->SetRenderState( D3DRS_STENCILFUNC,  D3DCMP_ALWAYS );
  273.     g_pd3dDevice->SetRenderState( D3DRS_STENCILFAIL,  D3DSTENCILOP_KEEP );  //ak je stencil test false
  274.     g_pd3dDevice->SetRenderState( D3DRS_STENCILPASS,  D3DSTENCILOP_KEEP );  //ak je stencil test a ztest true
  275.  
  276.     // If z-test passes, inc/decrement stencil buffer value
  277.     g_pd3dDevice->SetRenderState( D3DRS_STENCILREF,       0x0 );
  278.     g_pd3dDevice->SetRenderState( D3DRS_STENCILMASK,      0xffffffff );
  279.     g_pd3dDevice->SetRenderState( D3DRS_STENCILWRITEMASK, 0xffffffff );
  280.     
  281.     // Make sure that no pixels get drawn to the frame buffer
  282.     g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
  283.     g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND,  D3DBLEND_ZERO );
  284.     g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
  285.     
  286.     
  287.     Engine.SetZBuffer(true);
  288.  
  289.         ///////////////////
  290.         //increment Front//
  291.         ///////////////////
  292.  
  293.         //increment
  294.         //ak nieje pixel vidiet - zfail (ztest = false), pricitaj jednotu
  295.         g_pd3dDevice->SetRenderState( D3DRS_STENCILZFAIL, D3DSTENCILOP_INCR );
  296.  
  297.         //fron culling
  298.         g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW );
  299.  
  300.         // Draw front-side of shadow volume in stencil/z only
  301.         RenderShadowQuads();
  302.         
  303.  
  304.         //////////////////
  305.         //decrement Back//
  306.         //////////////////
  307.  
  308.         // Decrement stencil buffer value
  309.         // ak nieje pixel vidiet - zfail (ztest = false), odcitaj jednotu
  310.         g_pd3dDevice->SetRenderState( D3DRS_STENCILZFAIL, D3DSTENCILOP_DECR );
  311.  
  312.         // Now reverse cull order so back sides of shadow volume are written.
  313.         g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW);
  314.  
  315.         // Draw back-side of shadow volume in stencil/z only
  316.         RenderShadowQuads();
  317.  
  318.  
  319.     //reset
  320.     Engine.ResetToDefault();
  321.     Engine.SetBlendNone();
  322.  
  323. }
  324.  
  325. //------------------------------------------------------------------
  326. // Name: RenderShadowScreen()
  327. // Desc: vyrenderuje tien (stencil buffer) na obrazovku
  328. //------------------------------------------------------------------
  329. void STENCIL::RenderShadowScreen()
  330. {
  331.     //ak nieje zapnuty stencil prec
  332.     if (Engine.StencilShadows == false)
  333.         return;
  334.  
  335.     // Set render states
  336.     g_pd3dDevice->SetRenderState( D3DRS_ZENABLE,          FALSE );
  337.     g_pd3dDevice->SetRenderState( D3DRS_STENCILENABLE,    TRUE );
  338.     g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
  339.     g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA );
  340.     g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
  341.  
  342.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  343.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
  344.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
  345.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
  346.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
  347.     g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_MODULATE );
  348.  
  349.     // Only write where stencil value >= 1 (count indicates # of shadows that
  350.     // overlap that pixel)
  351.     g_pd3dDevice->SetRenderState( D3DRS_STENCILREF,  0x1 );
  352.     g_pd3dDevice->SetRenderState( D3DRS_STENCILFUNC, D3DCMP_LESSEQUAL );
  353.     g_pd3dDevice->SetRenderState( D3DRS_STENCILPASS, D3DSTENCILOP_KEEP );
  354.  
  355.     // Draw a big, gray square
  356.     g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEXSTENCILSQUARE );
  357.     g_pd3dDevice->SetStreamSource( 0, SquareVB, 0, sizeof(CUSTOMVERTEXSTENCILSQUARE) );
  358.     g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
  359.  
  360.     // Restore render states
  361.     Engine.ResetToDefault();
  362.     Engine.SetBlendNone();
  363.  
  364. }
  365.  
  366.  
  367.  
  368.